package org.budo.launcher.jetty.util;

import java.io.File;
import java.io.IOException;
import java.net.JarURLConnection;
import java.net.URL;
import java.net.URLClassLoader;
import java.net.URLConnection;
import java.security.CodeSource;
import java.util.ArrayList;
import java.util.List;
import java.util.jar.JarFile;

import org.eclipse.jetty.util.resource.Resource;

/**
 * @author lmw
 */
public class JettyLauncherUtil {
    public static List<URL> getUrlsOfJarsWithMetaInfResources() {
        ClassLoader classLoader = JettyLauncherUtil.class.getClassLoader();
        List<URL> staticResourceUrls = new ArrayList<URL>();
        if (classLoader instanceof URLClassLoader) {
            for (URL url : ((URLClassLoader) classLoader).getURLs()) {
                try {
                    if ("file".equals(url.getProtocol())) {
                        File file = new File(url.getFile());
                        if (file.isDirectory() && new File(file, "META-INF/resources").isDirectory()) {
                            staticResourceUrls.add(url);
                        } else if (isResourcesJar(file)) {
                            staticResourceUrls.add(url);
                        }
                    } else {
                        URLConnection connection = url.openConnection();
                        if (connection instanceof JarURLConnection) {
                            if (isResourcesJar((JarURLConnection) connection)) {
                                staticResourceUrls.add(url);
                            }
                        }
                    }
                } catch (IOException ex) {
                    throw new IllegalStateException(ex);
                }
            }
        }
        return staticResourceUrls;
    }

    public static boolean isResourcesJar(File file) {
        try {
            return isResourcesJar(new JarFile(file));
        } catch (IOException ex) {
            return false;
        }
    }

    private static boolean isResourcesJar(JarFile jar) throws IOException {
        try {
            return jar.getName().endsWith(".jar") && (jar.getJarEntry("META-INF/resources") != null);
        } finally {
            jar.close();
        }
    }

    public static boolean isResourcesJar(JarURLConnection connection) {
        try {
            return isResourcesJar(connection.getJarFile());
        } catch (IOException ex) {
            return false;
        }
    }

    public static Resource createResource(URL url) throws IOException {
        if ("file".equals(url.getProtocol())) {
            File file = new File(url.getFile());
            if (file.isFile()) {
                return Resource.newResource("jar:" + url + "!/META-INF/resources");
            }
        }
        return Resource.newResource(url + "META-INF/resources");
    }

    public static File getCodeSourceArchive(CodeSource codeSource) {
        try {
            URL location = (codeSource == null ? null : codeSource.getLocation());
            if (location == null) {
                return null;
            }

            String path;
            URLConnection connection = location.openConnection();
            if (connection instanceof JarURLConnection) {
                path = ((JarURLConnection) connection).getJarFile().getName();
            } else {
                path = location.toURI().getPath();
            }

            if (path.contains("!/")) {
                path = path.substring(0, path.indexOf("!/"));
            }
            return new File(path);
        } catch (Exception ex) {
            return null;
        }
    }
}